/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package rpg.gameSkeleton;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import rpg.Battle;
import rpg.Enemy;
import rpg.GameCharacter;
import rpg.PlayerCharacter;
import views.CharacterGraphics;
import views.GameBattleBar;

/**
 *
 * @author Emmanouil Samatas
 */
public class BattleBoard extends JPanel implements ActionListener {

    private final int BAR_HEIGHT = 60;
    private int bar_length;
    private Enemy selectedEnemy;
    private final String backgroundFile = "battle.jpg";
    private Image image;
    private PlayerCharacter myHero;
    private Battle battle;
    private List<Enemy> enemies;
    private GameBattleBar bar = new GameBattleBar();
    private List<BattleObserver> battleObserverList = new ArrayList<>();

    public BattleBoard(PlayerCharacter myPlayer) {
        setLayout(new BorderLayout(5, 5));
        this.myHero = myPlayer;


        this.battle = new Battle(myHero.getLevel(), false);
        enemies = battle.generateEnemies();

        JPanel enemyPanel = new JPanel();
        enemyPanel.setOpaque(false);
        enemyPanel.setLayout(new GridLayout(enemies.size(), 1));
        

        CharacterGraphics myHeroGraphics = new CharacterGraphics(myHero);
        myHeroGraphics.assignGraphics(myHero);
        
        add(myHeroGraphics, BorderLayout.WEST);
        for (Enemy enemy : enemies) {
            CharacterGraphics enemyGraphic = new CharacterGraphics(enemy);
            enemyGraphic.assignGraphics(enemy);
            
            enemyGraphic.addActionListener(this);
            enemyPanel.add(enemyGraphic);
        }
        add(enemyPanel, BorderLayout.EAST);
        add(bar, BorderLayout.SOUTH);
        bar.getAttackButton().addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                attackButton1ActionPerformed(evt);
            }
        });
        drawPlayerStatus();
        if (selectedEnemy != null) {
            drawPlayerStatus();
        }
        adjustSize();
        

    }

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(image, 0, 0, this);
        //drawHero(g2d);
        // drawEnemies(g2d);


    }
    private void adjustSize(){
         ImageIcon ii = new ImageIcon(this.getClass().getResource(backgroundFile));
        this.image = ii.getImage();
        Dimension size = new Dimension(image.getWidth(this) , image.getHeight(this) + BAR_HEIGHT);
        setPreferredSize(size);
        setMinimumSize(size);
        setMaximumSize(size);
        setSize(size);
    }

//    private void drawHero(Graphics2D g2d){
//        int staticX = 0;
//        int staticY = 175;
//        Image heroImage = myHero.getBigImage();
//        g2d.drawImage(heroImage,staticX,staticY,this);
//    }


    @Override
    public void actionPerformed(ActionEvent ae) {
       
        bar.getAttackButton().setEnabled(true);
        System.out.println(ae.getActionCommand());
        CharacterGraphics cg = (CharacterGraphics) ae.getSource();

        this.selectedEnemy = (Enemy) cg.getGameCharacter();
        drawEnemyStatus();


    }

    private void drawPlayerStatus() {
        String playerStatusName = drawNameString(myHero);
        bar.getPlayerNameLabel().setText(playerStatusName);

        JProgressBar playerHP = bar.getPlayerHpBar();
        playerHP.setMaximum(myHero.getMaxHealthPoints());
        playerHP.setValue(myHero.getHealthPoints());
        playerHP.setString(drawHpString(myHero));
        
        JProgressBar playerXp = bar.getXpBar();
        playerXp.setMaximum(myHero.getXpForNextLevel());
        playerXp.setValue(myHero.getExperience());
        

    }

    private void drawEnemyStatus() {
        String enemyStatusName = drawNameString(selectedEnemy);
        bar.getEnemyNameLabel().setText(enemyStatusName);

        JProgressBar enemyHp = bar.getMonsterHpBar();
        enemyHp.setVisible(true);
        enemyHp.setMaximum(selectedEnemy.getMaxHealthPoints());
        enemyHp.setValue(selectedEnemy.getHealthPoints());
        enemyHp.setString(drawHpString(selectedEnemy));




    }

    private String drawNameString(GameCharacter gc) {
        String playerText = gc.getCharacterName();
        String playerLevel = String.valueOf(gc.getLevel());
        StringBuilder sb = new StringBuilder();
        sb.append(playerText);
        sb.append(" (lvl. ");
        sb.append(playerLevel);
        sb.append(")");
        return sb.toString();

    }

    private String drawHpString(GameCharacter gc) {
        String maximumLife = String.valueOf(gc.getMaxHealthPoints());
        String currentLife = String.valueOf(gc.getHealthPoints());
        StringBuilder sb = new StringBuilder();
        sb.append("HP: ");
        sb.append(currentLife);
        sb.append("/");
        sb.append(maximumLife);
        return sb.toString();
    }

    private void attackButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        bar.getAttackButton().setEnabled(false);
        Timer timer = new Timer();
        myHero.attack(selectedEnemy);
        if(selectedEnemy.getHealthPoints() == 0){
            enemyDied(selectedEnemy);
        }
        drawEnemyStatus();
        drawPlayerStatus();


        final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
        List<Runnable> attacks = new ArrayList<>();
        for (final Enemy enemy : enemies) {
            Runnable task = new Runnable() {
                @Override
                public void run() {
                    if (enemy.getHealthPoints() > 0) {
                       
                        enemy.attack(myHero);
                        drawEnemyStatus();
                        drawPlayerStatus();
                        
                       }
                }
            };
            attacks.add(task);

        }
        Runnable task = new Runnable(){
            @Override
            public void run(){
                if(myHero.getHealthPoints() == 0){
                    playerDied();
            }
            }
        };
        attacks.add(task);
        for (int i = 0; i < attacks.size(); i++) {
            worker.schedule(attacks.get(i), i + 1, TimeUnit.SECONDS);
        }
      

//        bar.getAttackButton().setEnabled(true);   
    }
    
    private void enemyDied(Enemy deadMonster){
        System.out.println("I died!");
        myHero.addExperience(deadMonster.getExperience());
        drawPlayerStatus();
        enemies.remove(deadMonster);
        if(enemies.isEmpty()){
            battleEnded();
        }
        deadMonster.getCharacterGraphics().setVisible(false);
        
        
    }
    
    private void playerDied(){
        System.out.println("Player Died");
        myHero.getCharacterGraphics().setVisible(false);
        bar.remove(bar.getAttackButton());
        for(BattleObserver bo : battleObserverList){
            bo.battleEnded(false);
        }
        
    }
    
    private void battleEnded(){
        System.out.println("You won");
        for (BattleObserver bo : battleObserverList){
            bo.battleEnded(true);
        }
    }
 
    public void registerToBattleObserver(BattleObserver bo){
        battleObserverList.add(bo);
    }
    
}
